//
//  iTrackAnnotation.m
//  iTrack
//
//  Created by Sergei Sevriugin on 6/14/10.
//  Copyright 2010 Bellwood Systems. All rights reserved.
//

#import "iTrackAnnotation.h"


@implementation ITAnnotation

@synthesize coordinate;
@synthesize boundingMapRect;

@synthesize feature;
@synthesize locations;
@synthesize kind;
@synthesize mapViewController;


- (void) getFeatureParameters {
	
	NSArray*			feature_KMLValues	= [feature KMLValues];
	GDataXMLNode*		featureXMLNode		= [feature_KMLValues objectAtIndex:0];

	NSDate*				feature_timestamp	= [[feature updatedDate] date];
	
	NSUInteger			node_childCount		= [featureXMLNode childCount];
	GDataXMLNode*		node_child;
	NSString*			node_childName;
		
	NSComparisonResult	result				= -1;

	title									= [NSString stringWithString:[[feature title] stringValue]];
	
	for (int i = node_childCount - 1; i >= 0; i--) {
		node_child		= [featureXMLNode childAtIndex:i];
		node_childName	= [node_child name];
		result			= [node_childName compare:@"Point"];
		if (result == 0) {
			kind		= ITAnnotationKindPoint;
			break;
		}
		result			= [node_childName compare:@"LineString"];
		if (result == 0) {
			kind		= ITAnnotationKindLine;
			break;
		}
	}
	if (result != 0) {
		return;
	}
	// node_child is Point or LineString object now
	featureXMLNode		= node_child;
	node_childCount		= [featureXMLNode childCount];

	for (int i = node_childCount - 1; i >= 0; i--) {
		node_child		= [featureXMLNode childAtIndex:i];
		node_childName	= [node_child name];
		result			= [node_childName compare:@"coordinates"];
		if (result == 0) {
			break;			// coordinates
		}
	}
	// check if found
	if (result != 0 ) {
		return;
	}
	
	// node_child is coorditanes now
	featureXMLNode		= node_child;
	node_childCount		= [featureXMLNode childCount];
	
	for (int i = node_childCount - 1; i >= 0; i--) {
		node_child		= [featureXMLNode childAtIndex:i];
		node_childName	= [node_child name];
		result			= [node_childName compare:@"text"];
		if (result == 0) {
			break;			// text
		}
	}
	// check if found
	if (result != 0 ) {
		return;
	}
	// node_child is text now 
	CLLocation*				location			= nil;
	CLLocationCoordinate2D	theCoordinate		= {0.0,0.0};
	int						coordinate_count	= 0;
	double					alt					= 0.0;
	
	NSString*				coordinates_string	= [node_child stringValue];	
	NSScanner*				theScanner			= [NSScanner scannerWithString:coordinates_string];
	NSUInteger				position			= 0;
	
	while ([theScanner isAtEnd] == NO) {
		
		[theScanner scanDouble:&theCoordinate.longitude];
		
		position = [theScanner scanLocation] + 1;
		[theScanner setScanLocation:position];
		
		[theScanner scanDouble:&theCoordinate.latitude];
		
		position = [theScanner scanLocation] + 1;
		[theScanner setScanLocation:position];
		
		[theScanner scanDouble:&alt];
		
		location = [[CLLocation alloc] initWithCoordinate:theCoordinate 
													altitude:alt 
													horizontalAccuracy:0 
													verticalAccuracy:0 
													timestamp:feature_timestamp];
		
		[locations addObject:location];
				
		coordinate_count++;
	}
	
	// set description
	subtitle			= nil;
	featureXMLNode		= [feature_KMLValues objectAtIndex:0];
	node_childCount		= [featureXMLNode childCount];
	result				= -1;
	
	for (int i = 0 ; i < node_childCount; i++) {
		node_child		= [featureXMLNode childAtIndex:i];
		node_childName	= [node_child name];
		result			= [node_childName compare:@"description"];
		if (result == 0) {
			break;
		}
	}
	if (result != 0) {
		return;
	}
	
	featureXMLNode		= node_child;
	node_childCount		= [featureXMLNode childCount];
	result				= -1;
	
	for (int i = node_childCount - 1; i >= 0; i--) {
		node_child		= [featureXMLNode childAtIndex:i];
		node_childName	= [node_child name];
		result			= [node_childName compare:@"text"];
		if (result == 0) {
			break;			// text
		}
	}
	// check if found
	if (result != 0 ) {
		return;
	}
	
	subtitle	= [[NSString alloc] initWithString:[node_child stringValue]];		
}

- (NSString*) locationsToString {
	if (locations == nil) {
		return nil;
	}
	
	int	coordinate_count				= [locations count];

	if (coordinate_count == 0) {
		return nil;
	}
	
	NSMutableString*	result			= [NSMutableString stringWithCapacity:128];
	BOOL				first_obj		= YES;
	
	for (int i = 0; i < coordinate_count; i++) {
		if (first_obj) {
			first_obj = NO;
		}
		else {
			[result appendFormat:@"\n"];			
		}
		
		CLLocation*				location	= [locations objectAtIndex:i];
		CLLocationCoordinate2D	coord		= [location coordinate];
		
		[result appendFormat:@"%f,%f,%f",  coord.longitude, coord.latitude, [location altitude]];
	}
	return result;
}

- (void)setMapRect {
	if (locations == nil) {
		return;
	}
	
	int	coordinate_count		= [locations count];
	
	if (coordinate_count == 0) {
		return;
	}
	
	double minX, maxX, minY, maxY;

	CLLocation*		location	= [locations objectAtIndex:0];
	MKMapPoint		point		= MKMapPointForCoordinate([location coordinate]);
	
	minX = maxX = point.x;
	minY = maxY = point.y;

	for (int i = 1; i < coordinate_count; i++) {
		location	= [locations objectAtIndex:i];
		point		= MKMapPointForCoordinate([location coordinate]);
		
		minX = point.x < minX ? point.x : minX;
		maxX = point.x > maxX ? point.x : maxX;
		minY = point.y < minY ? point.y : minY;
		maxY = point.y > maxY ? point.y : maxY;
		
	}
	
	MKMapSize size	= MKMapSizeMake(maxX-minX, maxY-minY);
	boundingMapRect = MKMapRectMake(minX, minY, size.width, size.height);
	point.x			= MKMapRectGetMidX(boundingMapRect);
	point.y			= MKMapRectGetMidY(boundingMapRect);
	coordinate		= MKCoordinateForMapPoint(point);
}

- (id) initWithMapFeature:(GDataEntryMapFeature*) mapFeature {
	if( self = [super init ] )
	{
		[self setFeature:mapFeature];
		
		locations	= [[NSMutableArray alloc] initWithCapacity:10];
		kind		= ITAnnotationKindInvalid;
		
		[self getFeatureParameters];
		[self setMapRect];
	}
	return self;
}

- (id) initWithLocation:(CLLocation*) location andTitle:(NSString*) theTitle {
    self = [super init];
    if (self) {

		[self setFeature:[GDataEntryMapFeature featureEntryWithTitle:theTitle]];

		title			= [[NSString alloc] initWithString:theTitle];
		
		subtitle		= [[NSString alloc] initWithFormat:@"created by iTrack on %@", [NSDate date]];
		
		kind			= ITAnnotationKindPoint;
		
		locations		= [[NSMutableArray alloc] initWithCapacity:10];
		
		CLLocation* loc	= [[[CLLocation alloc] 
							initWithCoordinate:[location coordinate] 
							altitude:[location altitude]
							horizontalAccuracy:[location horizontalAccuracy]
							verticalAccuracy:[location verticalAccuracy] 
							timestamp:[location timestamp]] autorelease];
			
		[locations addObject:loc];
		[self setMapRect];
    }
    return self;
}

- (id) initWithLocation:(CLLocation*) location {
	return [self initWithLocation:location andTitle:@"New Empty Feature"];
}

- (void) saveFeature {
	NSString			*formatStr	= nil;
	
	if (kind == ITAnnotationKindPoint) {
		formatStr					= @"<Placemark xmlns='http://earth.google.com/kml/2.2'>"
												"<name>%@</name>"
												"<description>%@</description>"
												"<Style><IconStyle><Icon>"
												"<href>http://maps.gstatic.com/intl/en_ALL/mapfiles/ms/micons/blue-dot.png</href>"
												"</Icon></IconStyle></Style>"
												"<Point><coordinates>%@</coordinates></Point></Placemark>";
	}
	
	if (kind == ITAnnotationKindLine) {
		formatStr					= @"<Placemark xmlns='http://earth.google.com/kml/2.2'>"
												"<name>%@</name>"
												"<description>%@</description>"
												"<Style><LineStyle><color>73FF0000</color>"
												"<width>5</width>"
												"</LineStyle></Style>"
												"<LineString><tessellate>0</tessellate>"
												"<coordinates>%@</coordinates></LineString></Placemark>";
	}
	
	if (formatStr == nil) {
		NSLog(@"iTrack : cannot save this kind of feature - %d", kind);	
	}
	
	if (feature == nil) {
		feature						= [GDataEntryMapFeature featureEntryWithTitle:title];		
	}
	
	NSString		*summaryStr		= [NSString stringWithFormat:@"saved by iTrack on %@", [NSDate date]];
		
	[feature setSummaryWithString:summaryStr];
		
	NSString		*coordStr		= [self locationsToString];
	NSString		*titleStr		= [NSString stringWithString:[[feature title] stringValue]];
	NSString		*kmlStr			= [NSString stringWithFormat:formatStr, titleStr, summaryStr, coordStr];
		
	NSError			*error			= nil;
	NSXMLElement	*kmlElem		= nil;
									   
	kmlElem							= [[[NSXMLElement alloc] initWithXMLString:kmlStr
													error:&error] autorelease];
	if (kmlElem) {
		[feature addKMLValue:kmlElem];
	} 
	else {
		NSLog(@"iTrack: cannot make kml element, %@", error);
	}
}

- (void) addLocation:(CLLocation*) location {
	if (locations == nil) {
		kind = ITAnnotationKindInvalid;
		return;
	}
	
	[locations addObject:location];
	
	if ([locations count] > 1) {
		kind = ITAnnotationKindLine;
	}

	[self setMapRect];

}


-(IBAction)detailClicked:(id)sender {

	UIViewController *webViewController = [[UIViewController alloc] initWithNibName:@"WebView" bundle:nil];
	NSString*	HTMLString				= nil;
	UIWebView*	webVew					= (UIWebView*) [webViewController view];
	
	
	HTMLString = [NSString stringWithString:title];
		
	[webVew loadHTMLString:HTMLString baseURL:nil];
	[mapViewController.navigationController pushViewController:webViewController animated:YES];
	
	[webViewController release];
}

- (void)updateLocation:(CLLocation*)newLocation {
	
	CLLocation*	loc = [[[CLLocation alloc]
						initWithCoordinate:[newLocation coordinate] 
						altitude:[newLocation altitude]
						horizontalAccuracy:[newLocation horizontalAccuracy]
						verticalAccuracy:[newLocation verticalAccuracy] 
						timestamp:[newLocation timestamp]] autorelease];
			
	if ([locations count] == 0) {
		[locations addObject:loc];
	}
	else {
		[locations removeLastObject];
		[locations addObject:loc];
	}
	
	[self setMapRect];
}

- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate {
	if (kind == ITAnnotationKindInvalid || kind == ITAnnotationKindLine) {
		return;
	}
	
	CLLocation*		loc = [[[CLLocation alloc] 
							initWithLatitude:newCoordinate.latitude 
							longitude:newCoordinate.longitude] 
							autorelease];
	
	if ([locations count] == 0) {
		[locations addObject:loc];
	}
	else {
		[locations removeLastObject];
		[locations addObject:loc];
	}
	
	[self setMapRect];	
}

- (void)putOnMap {
	MKMapView*	mapView	= (MKMapView *) [mapViewController view];
	
	if (mapView == nil || kind == ITAnnotationKindInvalid) {
		return;
	}
	
	if (kind == ITAnnotationKindPoint) {
		[mapView addAnnotation:self];
	}
	else {
		[mapView addOverlay:self];
	}
}

- (void) removeFromMap {
	MKMapView*	mapView	= (MKMapView *) [mapViewController view];
	
	if (mapView == nil || kind == ITAnnotationKindInvalid) {
		return;
	}	
	
	if (kind == ITAnnotationKindPoint) {
		[mapView removeAnnotation:self];
	}
	else {
		[mapView removeOverlay:self];
	}
}

- (id) getAnnotation {
	
	if (kind == ITAnnotationKindInvalid) {
		return nil;
	}
	else {
		return self;
	}
}

- (CLLocation*) getLastLocation {
	if (locations == nil || [locations count] == 0) {
		CLLocation*		loc = [[[CLLocation alloc] 
									initWithLatitude:coordinate.latitude 
									longitude:coordinate.longitude] 
									autorelease];
		return loc;
	}
	else {
		return [locations lastObject];
	}
}

- (NSString *)title {
	return title;
}

- (NSString *)subtitle {
	return subtitle;
}

- (BOOL) isPath {
	if (kind == ITAnnotationKindLine) {
		return YES;
	}
	else {
		return NO;
	}
}

- (BOOL) isPoint {
	if (kind == ITAnnotationKindPoint) {
		return YES;
	}
	else {
		return NO;
	}
}

- (void)dealloc {
	
	[title release];
	[subtitle release];
	[locations release];
	    
	[super dealloc];
}


@end
